<?php

class ProxyController extends CommonController {

	public function __construct() {
		parent::__construct();
	}

	public function coderAction(){
		$file = PATH_ROOT . '/../texas/' . str_replace('..', '', $this->requestGet('file'));
		if(!file_exists($file)) {
			$this->jsonError('文件名有误，请重新输入！');
		}

		$this->jsonSuccess($file, file_get_contents($file));
	}

	public function filesAction(){
		$files = scandir(PATH_ROOT . '/../texas/api/v5/');
		array_splice($files, 0, 2);
		sort($files);
		$this->jsonSuccess('', $files);
	}

	public function methodsAction(){
		define('IN_WEB', TRUE);
		$class = $this->requestGet('class');
		include_once PATH_ROOT . '/../texas/model/oo.php';
		include_once PATH_ROOT . '/../texas/api/v5/Server.php';
		include_once PATH_ROOT . '/../texas/api/v5/' . $class . '.php';
		$ref = new ReflectionClass(new $class());
		$methods = array();
		$data = $ref->getMethods(ReflectionMethod::IS_PUBLIC);
		foreach ($data as $item) {
			$methods[] = $item->name;
		}
		sort($methods);
		$this->jsonSuccess('', $methods);
	}

	public function debugAction() {
		$url = $_POST['url'];
		$postfields = $this->genParams();
		$verifyType = (int) $_POST['verifyType'];
		$v8 = isset($_POST['v8']) ? $_POST['v8'] : 0;
		$headers = array();	
		if($verifyType){
			$xTunnelVerify = $this->genXTunnelVerfiy();
			$headers[] = "x-tunnel-verify: {$xTunnelVerify}";
		}

		if($v8){
			$headers[] = "api-v8: 1";
		}

		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_POST, TRUE);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);	
		curl_setopt($ch, CURLOPT_TIMEOUT, 10);
		curl_exec($ch);
		curl_close($ch);
	}

	private function genParams(){
		$sigKey = $_POST['sigKey'];

		$param = json_decode($_POST['param'], true);

		$guest = isset($_POST['guest']) ? $_POST['guest'] : 0;

		$data = array(
			'api' => (int) $_POST['api'],
			'unid' => (int) $_POST['unid'],
			'sid' => $guest ? 79 : (int) $_POST['sid'],
			'method' => $_POST['class'] . '.' . $_POST['method'],
			'mid' => (int) $_POST['mid'],
			'mtkey' => $_POST['mtkey'],
			'langtype' => $_POST['language'],
			'param' => is_null($param) ? array() : $param,
			'version' => $_POST['version']
		);
		//var_dump($data, $sigKey);die;
		$data['sig'] = md5($this->joins($data, $data['mtkey'], $sigKey));
		$jsonData = json_encode($data);
		return 'api=' . $jsonData;
	}

	private function joins($arg, $mtkey, $letter) {
		static $joins_counter = 0;
		if (++$joins_counter > 500) {
			die('possible deep recursion attack!');
		}
		$str = $letter;
		if (!is_object($arg)) {
			if (is_null($arg) || is_bool($arg)) {
				$str .= '';
			} elseif (is_string($arg) || is_numeric($arg)) {
				$str .= 'T' . $mtkey . preg_replace('/[^0-9a-z]/i', '', $arg, -1);
			} else {
				ksort($arg, SORT_STRING);
				foreach ($arg as $key => $value) {
					$str .= ($key . '=' . $this->joins($value, $mtkey, $letter));
				}
			}
		}
		return $str;
	}

	private function genXTunnelVerfiy() {
		static $byteMap = array(
	0x70, 0x2F, 0x40, 0x5F, 0x44, 0x8E, 0x6E, 0x45, 0x7E, 0xAB, 0x2C, 0x1F, 0xB4, 0xAC, 0x9D, 0x91,
	0x0D, 0x36, 0x9B, 0x0B, 0xD4, 0xC4, 0x39, 0x74, 0xBF, 0x23, 0x16, 0x14, 0x06, 0xEB, 0x04, 0x3E,
	0x12, 0x5C, 0x8B, 0xBC, 0x61, 0x63, 0xF6, 0xA5, 0xE1, 0x65, 0xD8, 0xF5, 0x5A, 0x07, 0xF0, 0x13,
	0xF2, 0x20, 0x6B, 0x4A, 0x24, 0x59, 0x89, 0x64, 0xD7, 0x42, 0x6A, 0x5E, 0x3D, 0x0A, 0x77, 0xE0,
	0x80, 0x27, 0xB8, 0xC5, 0x8C, 0x0E, 0xFA, 0x8A, 0xD5, 0x29, 0x56, 0x57, 0x6C, 0x53, 0x67, 0x41,
	0xE8, 0x00, 0x1A, 0xCE, 0x86, 0x83, 0xB0, 0x22, 0x28, 0x4D, 0x3F, 0x26, 0x46, 0x4F, 0x6F, 0x2B,
	0x72, 0x3A, 0xF1, 0x8D, 0x97, 0x95, 0x49, 0x84, 0xE5, 0xE3, 0x79, 0x8F, 0x51, 0x10, 0xA8, 0x82,
	0xC6, 0xDD, 0xFF, 0xFC, 0xE4, 0xCF, 0xB3, 0x09, 0x5D, 0xEA, 0x9C, 0x34, 0xF9, 0x17, 0x9F, 0xDA,
	0x87, 0xF8, 0x15, 0x05, 0x3C, 0xD3, 0xA4, 0x85, 0x2E, 0xFB, 0xEE, 0x47, 0x3B, 0xEF, 0x37, 0x7F,
	0x93, 0xAF, 0x69, 0x0C, 0x71, 0x31, 0xDE, 0x21, 0x75, 0xA0, 0xAA, 0xBA, 0x7C, 0x38, 0x02, 0xB7,
	0x81, 0x01, 0xFD, 0xE7, 0x1D, 0xCC, 0xCD, 0xBD, 0x1B, 0x7A, 0x2A, 0xAD, 0x66, 0xBE, 0x55, 0x33,
	0x03, 0xDB, 0x88, 0xB2, 0x1E, 0x4E, 0xB9, 0xE6, 0xC2, 0xF7, 0xCB, 0x7D, 0xC9, 0x62, 0xC3, 0xA6,
	0xDC, 0xA7, 0x50, 0xB5, 0x4B, 0x94, 0xC0, 0x92, 0x4C, 0x11, 0x5B, 0x78, 0xD9, 0xB1, 0xED, 0x19,
	0xE9, 0xA1, 0x1C, 0xB6, 0x32, 0x99, 0xA3, 0x76, 0x9E, 0x7B, 0x6D, 0x9A, 0x30, 0xD6, 0xA9, 0x25,
	0xC7, 0xAE, 0x96, 0x35, 0xD0, 0xBB, 0xD2, 0xC8, 0xA2, 0x08, 0xF3, 0xD1, 0x73, 0xF4, 0x48, 0x2D,
	0x90, 0xCA, 0xE2, 0x58, 0xC1, 0x18, 0x52, 0xFE, 0xDF, 0x68, 0x98, 0x54, 0xEC, 0x60, 0x43, 0x0F
		);

		$version = $_POST['verifyVersion'];
		$hashKey = $_POST['hashKey'];
		$seed = rand(1, 255);

		$dataKeys = array(
			'api',
			'appID',
			'appVer',
			'binHash', 
			'blistHash',
			'iOSType', 
			'iOSVer', 
			'iOSModel',
			'isJailBreak',
			'macAddr',
			'name',
			'openUDID',
			'udid',
			'z3GAddr',
			'zSeed',
			'zUid'
		);
		$data = array();
		foreach($dataKeys as $key){
			$data[$key] = isset($_POST[$key]) ? $_POST[$key] : '';
		}
		$data['macID'] = empty($data['udid']) ? '' : md5($data['udid']);
		$jsonData = json_encode($data);

		$encodeData = '';
		for ($i = 0, $l = strlen($jsonData); $i < $l; $i++) {
			$encodeData .= chr(array_search(ord($jsonData{$i}), $byteMap) ^ $seed);
		}

		if( function_exists( 'mhash' ) ) {
			$sig = mhash( MHASH_SHA1, $jsonData, $hashKey );
		} elseif ( function_exists( 'hash_hmac' ) ) {
			$sig = hash_hmac( "sha1", $jsonData, $hashKey, true );
		} else {
			exit('mhash or hash_hmac function not exsits.' . __FILE__ . ' : ' . __LINE__);
		}

		$seed = dechex($seed);
		$encodeData = base64_encode($encodeData);
		$sig = base64_encode($sig);

		return "{$version}&{$seed}&{$encodeData}&{$sig}";
	}

	public function jsonpAction() {
		$sigKey = '!(~_~)(&_&)(*_*)(@_@)(#_#)(^_^)!';
		$encryptKey = 'AAas%fasS#9Aasd^S9a!df(Dasdf9ADj';

		$url = $this->requestPost('url');
		unset($_POST['url']);
		$buffer = self::uencrypt($_POST, $sigKey, $encryptKey);
		$postFields = "buffer={$buffer}";
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
		curl_setopt($ch, CURLOPT_TIMEOUT, 10);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		$back = curl_exec($ch);
		curl_close($ch);
		$data = self::udecrypt($back, $sigKey, $encryptKey);
		$this->jsonSuccess('', $data);
		exit();
	}
	
	static function uencrypt($data, $sigKey, $encryptKey) {
		if(!is_array($data)) return false;
		$data['time'] = time();
		$data['sig'] = sha1(implode(',', $data) . $sigKey);
		$json = json_encode($data);
		$len = strlen($json);
		$keyLen = strlen($encryptKey);
		$result = "";
		for($i = 0;$i < $len;$i += 1) {
			$j = $i % $keyLen;
			$result .=  $json{$i} ^ $encryptKey{$j};
		}
		return base64_encode($result);
	}
	
	static function udecrypt($buffer, $sigKey, $encryptKey) {
		$buffer = base64_decode($buffer);
		$len = strlen($buffer);
		$keyLen = strlen($encryptKey);
		$json = "";
		for($i = 0;$i < $len;$i += 1) {
			$j = $i % $keyLen;
			$json .= $buffer{$i} ^ $encryptKey{$j};
		}
		$data = json_decode($json, true);
		if(is_null($data) || !isset($data['sig']) || count($data) < 2) return false;
		$sig = $data['sig'];
		unset($data['sig']);
		if(strcmp(sha1(implode(',', $data) . $sigKey), $sig) != 0) return false;
		unset($data['time']);
		return $data;
	}

	public function checkAction() {
		$addresses = $this->requestGet('address');
		if(!is_array($addresses) || empty($addresses)) {
			$this->jsonError('Wrong address');
		}

		$result = array();
		
		foreach ($addresses as $id => $address) {
			$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
			if(socket_connect($socket, $address[0], $address[1])) {
				$result[$id] = 1;
				socket_close($socket);
			} else {
				$result[$id] = 0;
			}
		}
		$this->jsonSuccess('', $result);
	}
}

?>